package cn.pconline.officialclub.web;

import cn.pconline.autoclub.config.SystemConfig;
import cn.pconline.autoclub.entity.User;
import cn.pconline.autoclub.service.UserService;
import cn.pconline.autoclub.util.EncodeUtils;
import cn.pconline.autoclub.util.Result;
import cn.pconline.autoclub.util.WebUtils;
import cn.pconline.autoclub.util.excel.ExcelGenerator;
import cn.pconline.autoclub.web.UserAuth;
import cn.pconline.officialclub.entity.OCommonMember;
import cn.pconline.officialclub.service.OMemberService;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * controller帮助类，主要提供了一些权限验证方法和响应输出方法
 *
 * 约定：需要权限验证的get请求返回页面 post请求返回json
 *
 * 对于需要登录的操作，一定要统一返回同一种格式：(参照Result类，尽量调用Result类方法)
 * {code:"",message:"",data:"",pageCount:"",pageNo:"",pageSize:"",total:""}
 * code字段一定要有，其他的根据实际情况
 *
 * @author <a href="mailto:chensy0203@163.com">chensy</a>
 */
public class WebKit {

    @Autowired
    protected UserAuth userAuth;
    @Autowired
    protected SystemConfig systemConfig;
    @Autowired
    protected OMemberService oMemberService;
    @Autowired
    protected UserService userService;
    protected static final Logger log = LoggerFactory.getLogger(WebKit.class);
    protected final static int DEF_MAX_PAGESIZE = 100;
    protected final static int DEF_MIN_PAGESIZE = 1;
    protected final static int DEF_PAGE_NUM = 1;
    protected final static int DEF_PAGE_SIZE = 20;
    protected static final int XSSENCODECODE = 1;
    protected static final String XSS_ENCODE = "xssEncode";

    /**
     * 输出json结果，不带callback参数
     *
     * @param resp
     * @param result
     */
    protected void printMsg(HttpServletResponse resp, Result result) {
        printMsg(resp, result, null);
    }

    /**
     * 输出字符串，带callback参数
     *
     * @param resp
     * @param rs
     * @param callback
     */
    protected void printMsg(HttpServletResponse resp, String rs, String callback) {
        callback = EncodeUtils.encodeForHTMLFilterNull(callback);
        try {
            java.io.PrintWriter w = resp.getWriter();
            if (StringUtils.isNotBlank(callback)) {
                w.print(callback + "(" + rs + ")");
            } else {
                w.print(rs);
            }
            w.flush();
            w.close();
        } catch (IOException ex) {
            log.error("response输出出错了", ex);
        }
    }

    /**
     * 输出字符串，带windowname
     *
     * @param resp
     * @param rs
     * @param callback
     */
    protected void printMsg(HttpServletResponse resp, String rs, int windowname) {
        try {
            java.io.PrintWriter w = resp.getWriter();
            if (windowname > 0) {
                w.print("<script>window.name='" + rs + "'</script>");
            } else {
                w.print(rs);
            }
            w.flush();
            w.close();
        } catch (IOException ex) {
            log.error("response输出出错了", ex);
        }
    }

    /**
     * 输出json结果，带callback参数
     *
     * @param resp
     * @param result
     * @param callback
     */
    protected void printMsg(HttpServletResponse resp, Result result, String callback) {
        printMsg(resp, result.toString(), callback);
    }

    /**
     * 输出JSON结果,带windowname
     *
     * @param resp
     * @param result
     * @param windowName
     */
    protected void printMsg(HttpServletResponse resp, Result result, int windowName) {
        printMsg(resp, result.toString(), windowName);
    }

    /**
     * 输出excel文件
     *
     * @param resp
     * @param fileName
     * @param data
     * @param header
     */
    protected void printExcelFile(HttpServletResponse resp, String fileName,
            List<Map<String, Object>> data, List<String> header) {
        OutputStream os = null;
        try {
            String filename = URLEncoder.encode(fileName, "UTF-8");
            os = resp.getOutputStream();
            // 清空输出流
            resp.reset();
            // 定义输出类型
            resp.setContentType("application/vnd.ms-excel");
            resp.setHeader("Content-disposition", "attachment; filename=" + new String((filename + ".xls").getBytes(), "UTF-8"));
            ExcelGenerator.generate(data, os, header);
            os.flush();
            os.close();
        } catch (IOException ex) {
            log.error("printExcelFile fail--IOException!", ex);
        } finally {
            try {
                if (null != os) {
                    os.close();
                }
            } catch (IOException ex) {
                log.error("printExcelFile fail when close outputStream!", ex);
            }
        }
    }

    /**
     * 如果用户未登录，返回NULL！ 使用的地方需要注意，当返回NULL的时候，要return;
     *
     * @param request
     * @param resp
     */
    protected User checkUser(HttpServletRequest request, HttpServletResponse resp) {
        User user = userAuth.getUser(request, resp);
        if (user.getUid() <= 0) {
            if (WebUtils.isGet(request)) {
                try {
                    String url = systemConfig.getUcRoot()
                            + "/login.jsp?return="
                            + request.getRequestURL();
                    if (request.getQueryString() != null) {
                        url += "?" + request.getQueryString();
                    }
                    resp.sendRedirect(url);
                    return null;
                } catch (IOException ex) {
                    log.error("checkAndSetUser error");
                }
            } else {
                printMsg(resp, Result.noLogin());
                return null;
            }
        }
        return user;
    }

    /**
     * 判断用户是否登录，是否是会员！使用的地方需要注意，当返回NULL的时候，要return;
     *
     * @param request 包含：oClubId
     * @param resp
     * @param user
     */
    protected OCommonMember checkMember(HttpServletRequest request, HttpServletResponse resp) {
        User user = checkUser(request, resp);
        if (user == null) {
            return null;
        }
        return checkMember(request, resp, user);
    }

    /**
     * 判断用户是否是会员！使用的地方需要注意，当返回NULL的时候，要return;
     *
     * @param request
     * @param resp
     * @param user 不允许为NULL
     * @return
     */
    protected OCommonMember checkMember(HttpServletRequest request, HttpServletResponse resp, User user) {
        long clubId = WebUtils.paramLong(request, "oClubId", 0);
        OCommonMember member = oMemberService.findCommonMember(user.getUid(), clubId);
        if (member == null) {
            if (WebUtils.isGet(request)) {
                try {
                    resp.sendError(403);
                    return null;
                } catch (IOException ex) {
                    log.error("error", ex);
                }
            } else {
                printMsg(resp, Result.noPermission("非会员"));
                return null;
            }
        }
        return member;
    }

    /**
     * 判断用户是否登录，是否是会员，是否是管理员！使用的地方需要注意，当返回NULL的时候，要return;
     *
     * @param request
     * @param resp
     * @param member
     */
    protected boolean isAdmin(HttpServletRequest request, HttpServletResponse resp) {
        OCommonMember member = checkMember(request, resp);
        if (member == null) {
            return false;
        }
        if (!member.isAdmin()) {
            if (WebUtils.isGet(request)) {
                try {
                    resp.sendError(403);
                    return false;
                } catch (IOException ex) {
                    log.error("error", ex);
                }
            } else {
                printMsg(resp, Result.noPermission("非管理员"));
                return false;
            }
        }
        return true;
    }

    /**
     * 判断用户是否登录，是否是会员，是否是管理员！使用的地方需要注意，当返回NULL的时候，要return;
     *
     * @param request
     * @param resp
     * @param member
     */
    protected boolean isAdmin(HttpServletRequest request, HttpServletResponse resp, OCommonMember member) {
        if (member == null || (!member.isAdmin())) {
            if (WebUtils.isGet(request)) {
                try {
                    resp.sendError(403);
                    return false;
                } catch (IOException ex) {
                    log.error("error", ex);
                }
            } else {
                printMsg(resp, Result.noPermission("非管理员"));
                return false;
            }
        }
        return true;
    }

    /**
     * 判断用户是否登录，是否是会员，是否是会长！使用的地方需要注意，当返回NULL的时候，要return;
     *
     * @param request
     * @param resp
     * @param member
     */
    protected boolean isPresident(HttpServletRequest request, HttpServletResponse resp) {
        OCommonMember member = checkMember(request, resp);
        if (member == null || (member.getAdminType() != OCommonMember.ADMIN_TYPE_PRESIDENT)) {
            if (WebUtils.isGet(request)) {
                try {
                    resp.sendError(403);
                    return false;
                } catch (IOException ex) {
                    log.error("error", ex);
                }
            } else {
                printMsg(resp, Result.noPermission("非会长"));
                return false;
            }
        }
        return true;
    }

    /**
     * 校验最大页码是否超出真实页码 当返回false的时候，要return;
     *
     * @param resp
     * @param pageNo
     * @param pageCount
     */
    protected boolean checkPageMaxNo(HttpServletRequest req, HttpServletResponse resp, int pageNo,
            int pageCount) {
        if (pageNo > pageCount) {
            if (WebUtils.isGet(req)) {
                try {
                    resp.sendError(404);
                } catch (IOException ex) {
                    log.error("checkPageMaxNo fail!", ex);
                }
            } else {
                printMsg(resp, Result.dataError("页码太大"));
            }
            return false;
        }
        return true;
    }

    protected String redirect404(HttpServletResponse response) {
        try {
            response.sendError(404);
        } catch (Exception ex) {
            log.error("redirect404 fial!", ex);
        }
        return "/template/common/notFoundPage";
    }

    protected String redirect403(HttpServletResponse response) {
        try {
            response.sendError(403);
        } catch (Exception ex) {
            log.error("redirect403 fial!", ex);
        }
        return "/template/common/noAuthPage";
    }
    protected static String PAGE_NO_AUTH = "/template/common/noAuthPage";

    protected String getPcTemplPath(String path) {
        return "/template/official/pc" + path;
    }
}
